#include "HoleParser.h"

#include "IdRefParser.h"
#include "DoubleParser.h"
#include "PlatingStatusParser.h"
#include "QStringParser.h"

#include <QXmlStreamReader>
#include <QString>

namespace Ipc2581b
{

HoleParser::HoleParser(
    QStringParser *&_nameParser
    , DoubleParser *&_diameterParser
    , PlatingStatusParser *&_platingStatusParser
    , DoubleParser *&_plusTolParser
    , DoubleParser *&_minusTolParser
    , DoubleParser *&_xParser
    , DoubleParser *&_yParser
    , IdRefParser *&_specRefParser
):    m_nameParser(_nameParser)
    , m_diameterParser(_diameterParser)
    , m_platingStatusParser(_platingStatusParser)
    , m_plusTolParser(_plusTolParser)
    , m_minusTolParser(_minusTolParser)
    , m_xParser(_xParser)
    , m_yParser(_yParser)
    , m_specRefParser(_specRefParser)
{

}

bool HoleParser::parse(QXmlStreamReader *reader)
{
    /* Pre */

    m_result.reset(new Hole());

    /* Attributes */

    QStringRef data;
    if (reader->attributes().hasAttribute(QStringLiteral("name")))
    {
        data = reader->attributes().value(QStringLiteral("name"));
        if (!m_nameParser->parse(reader, data))
            return false;
        m_result->name = m_nameParser->result();
    }
    else
    {
        reader->raiseError(QStringLiteral("name: Attribute is required"));
        return false;
    }
    if (reader->attributes().hasAttribute(QStringLiteral("diameter")))
    {
        data = reader->attributes().value(QStringLiteral("diameter"));
        if (!m_diameterParser->parse(reader, data))
            return false;
        m_result->diameter = m_diameterParser->result();
    }
    else
    {
        reader->raiseError(QStringLiteral("diameter: Attribute is required"));
        return false;
    }
    if (reader->attributes().hasAttribute(QStringLiteral("platingStatus")))
    {
        data = reader->attributes().value(QStringLiteral("platingStatus"));
        if (!m_platingStatusParser->parse(reader, data))
            return false;
        m_result->platingStatus = m_platingStatusParser->result();
    }
    else
    {
        reader->raiseError(QStringLiteral("platingStatus: Attribute is required"));
        return false;
    }
    if (reader->attributes().hasAttribute(QStringLiteral("plusTol")))
    {
        data = reader->attributes().value(QStringLiteral("plusTol"));
        if (!m_plusTolParser->parse(reader, data))
            return false;
        m_result->plusTol = m_plusTolParser->result();
    }
    else
    {
        reader->raiseError(QStringLiteral("plusTol: Attribute is required"));
        return false;
    }
    if (reader->attributes().hasAttribute(QStringLiteral("minusTol")))
    {
        data = reader->attributes().value(QStringLiteral("minusTol"));
        if (!m_minusTolParser->parse(reader, data))
            return false;
        m_result->minusTol = m_minusTolParser->result();
    }
    else
    {
        reader->raiseError(QStringLiteral("minusTol: Attribute is required"));
        return false;
    }
    if (reader->attributes().hasAttribute(QStringLiteral("x")))
    {
        data = reader->attributes().value(QStringLiteral("x"));
        if (!m_xParser->parse(reader, data))
            return false;
        m_result->x = m_xParser->result();
    }
    else
    {
        reader->raiseError(QStringLiteral("x: Attribute is required"));
        return false;
    }
    if (reader->attributes().hasAttribute(QStringLiteral("y")))
    {
        data = reader->attributes().value(QStringLiteral("y"));
        if (!m_yParser->parse(reader, data))
            return false;
        m_result->y = m_yParser->result();
    }
    else
    {
        reader->raiseError(QStringLiteral("y: Attribute is required"));
        return false;
    }

    /* Elements */

    while (reader->readNextStartElement())
    {
        auto name = reader->name();
        if (name == QStringLiteral("SpecRef"))
        {
            if (!m_specRefParser->parse(reader))
                return false;
            auto result = m_specRefParser->result();
            m_result->specRefList.append(result);
        }
        else
            reader->skipCurrentElement();
    }

    /* Post */

    // TODO: Check multiplicity of elements/attributes

    return true;
}

Hole *HoleParser::result()
{
    return m_result.take();
}

}